/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.controller;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.spi.listener.ApplicationListener;
import cn.easyplatform.web.WebApps;
import org.apache.commons.io.FileUtils;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.metainfo.ComponentInfo;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zkmax.zul.Cardlayout;
import org.zkoss.zkmax.zul.Stepbar;
import org.zkoss.zul.*;

import java.io.File;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class SetupController extends SelectorComposer<Borderlayout> {

    @Wire("textbox#dbUser")
    private Textbox dbUser;

    @Wire("textbox#dbPass")
    private Textbox dbPass;

    @Wire("textbox#dbAddress")
    private Textbox dbAddress;

    @Wire("intbox#dbPort")
    private Intbox dbPort;

    @Wire("textbox#dbName")
    private Textbox dbName;

    @Wire("cardlayout#card")
    private Cardlayout card;

    @Wire("progressmeter#progress")
    private Progressmeter progress;

    @Wire("label#progressLabel")
    private Label progressLabel;

    @Wire("label#progressTitle")
    private Label progressTitle;

    @Wire("a#motion")
    private A motion;

    @Wire("label#motionLabel")
    private Label motionLabel;

    @Wire("stepbar#stepbar")
    private Stepbar stepbar;

    @Wire("button#next")
    private Button next;

    @Override
    public void doAfterCompose(Borderlayout comp) throws Exception {
        super.doAfterCompose(comp);
        comp.getPage().setTitle(Labels.getLabel("setup.title"));
        if (WebApps.me().get("MOD_READY") == null) {
            next.setDisabled(true);
            dbUser.setReadonly(true);
            dbPass.setReadonly(true);
            dbAddress.setReadonly(true);
            dbPort.setReadonly(true);
            dbName.setReadonly(true);
        }
    }

    @Listen("onClick=#next")
    public void next(Event event) {
        if (card.getSelectedIndex() == 0) {
            File metadataFile = new File(System.getProperty("easyplatform.home") + "/scheme/app_metadata.sql");
            File bizFile = new File(System.getProperty("easyplatform.home") + "/scheme/app_biz.sql");
            if (!metadataFile.isFile() || !bizFile.isFile())
                throw new WrongValueException(event.getTarget(), Labels.getLabel("setup.scheme.error"));
            if (Strings.isBlank(dbUser.getValue()))
                throw new WrongValueException(dbUser, Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("setup.db.user")}));
            if (Strings.isBlank(dbPass.getValue()))
                throw new WrongValueException(dbPass, Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("setup.db.pass")}));
            if (Strings.isBlank(dbAddress.getValue()))
                throw new WrongValueException(dbAddress, Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("setup.db.address")}));
            if (dbPort.getValue() == null || dbPort.getValue() <= 0)
                throw new WrongValueException(dbPort, Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("setup.db.port")}));
            if (Strings.isBlank(dbName.getValue()))
                throw new WrongValueException(dbName, Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("setup.db.name")}));
            if (!card.getDesktop().isServerPushEnabled()) {
                card.getDesktop().enableServerPush(true);
            }
            Map<String, String> properties = new HashMap<>();
            properties.put("username", dbUser.getValue());
            properties.put("password", dbPass.getValue());
            properties.put("address", dbAddress.getValue());
            properties.put("port", String.valueOf(dbPort.getValue()));
            properties.put("name", dbName.getValue());
            card.next();
            stepbar.next();
            ((Button) event.getTarget()).setDisabled(true);
            WebApps.me().setup(properties, new ApplicationListener() {
                @Override
                public void publish(String s, String s1, Serializable serializable, String... strings) {
                    Executions.schedule(card.getDesktop(), (EventListener<Event>) evt -> {
                        Number number = (Number) evt.getData();
                        progress.setValue(number.intValue());
                        if (Strings.isBlank(s)) {
                            progressLabel.setValue(evt.getName());
                            if (s != null)
                                stepbar.getActiveStep().setError(true);
                        } else {
                            progressTitle.setValue(s);
                        }
                        if (progress.getValue() == 100) {
                            ((Button) evt.getTarget()).setDisabled(false);
                            stepbar.getActiveStep().setComplete(true);
                        }
                    }, new Event(s1, event.getTarget(), serializable));
                }

                @Override
                public void send(String s, String s1, Serializable serializable, String... strings) {

                }

                @Override
                public void close() {

                }
            });
        } else if (card.getSelectedIndex() == 1) {
            card.next();
            stepbar.next();
            motion.setIconSclass("z-icon-cog z-icon-spin");
            ((Button) event.getTarget()).setDisabled(true);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Executions.schedule(card.getDesktop(), (EventListener<Event>) event -> {
                            motionLabel.setValue(Labels.getLabel("setup.service.starting"));
                        }, new Event(event.getName(), event.getTarget(), null));
                        WebApps.me().startup();
                        Executions.schedule(card.getDesktop(), (EventListener<Event>) event -> {
                            motion.setIconSclass("z-icon-cog");
                            motionLabel.setValue(Labels.getLabel("setup.service.started"));
                            stepbar.getActiveStep().setComplete(true);
                            Button btn = (Button) event.getTarget();
                            btn.setLabel(Labels.getLabel("setup.service.redirect"));
                            btn.setDisabled(false);
                        }, new Event(event.getName(), event.getTarget(), null));
                        WebApps.me().remove("MOD_READY");
                    } catch (Exception e) {
                        Executions.schedule(card.getDesktop(), (EventListener<Event>) event -> {
                            motion.setIconSclass("z-icon-cog");
                            motionLabel.setValue(Labels.getLabel("setup.service.fail") + e.getMessage());
                            stepbar.getActiveStep().setError(true);
                        }, new Event(event.getName(), event.getTarget(), null));
                    }
                }
            }).start();
        } else {
            Executions.sendRedirect("/login.go");
        }
    }
}
